package com.devilvan.betrice.houseprice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devilvan.betrice.annotation.BetriceRunTime;
import com.devilvan.betrice.common.BetriceCommon;
import com.devilvan.betrice.exception.BetriceException;
import com.devilvan.betrice.houseprice.component.HousePriceRedisHelper;
import com.devilvan.betrice.request.BetriceHttpBuilder;
import com.devilvan.betrice.request.pojo.BetriceHttpClient;
import com.devilvan.betrice.request.component.HttpClientComponent;
import com.devilvan.betrice.exception.constant.BetriceExceptionConstant;
import com.devilvan.betrice.houseprice.constant.HousePriceRedisKeyConstant;
import com.devilvan.betrice.houseprice.service.HousePriceService;
import com.devilvan.betrice.houseprice.mapper.HousePriceMapper;
import com.devilvan.betrice.houseprice.po.HousePricePo;
import com.devilvan.betrice.proxy.service.ProxyService;
import com.devilvan.betrice.houseprice.vo.HousePriceVo;
import com.devilvan.betrice.util.UCopy;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Evad.Wu
 * @Description 房价信息 业务逻辑接口
 * @date 2022-07-12
 */
@Lazy
@Slf4j
@Service
@SuppressWarnings(value = "unused")
public class HousePriceServiceImpl extends ServiceImpl<HousePriceMapper, HousePricePo> implements HousePriceService {
    /**
     * 最后修改时间超过阈值，则冗余新增
     */
    private static final int PASS_DAY_THREHOLD = 30;

    @Resource(name = "httpClientComponent")
    private HttpClientComponent httpClientComponent;
    @Resource(name = "housePriceRedisHelper")
    private HousePriceRedisHelper housePriceRedisComponent;
    @Resource(name = "redisson")
    private RedissonClient redisson;

    @Resource(name = "proxyServiceImpl")
    private ProxyService proxyService;


    @Override
    @BetriceRunTime
    @Async(value = "threadPoolExecutor")
    public void doFangke(HousePriceRedisKeyConstant constant) {
        String url = constant.getUrl();
        Map<Object, Object> map = housePriceRedisComponent.generateRedisHeaderDto(constant);
        String name = constant.name();
        Integer totalPg = Integer.parseInt((String) map.get(BetriceCommon.SUFFIX_TOTAL_PAGE));
        Integer currentPg = Integer.parseInt((String) map.get(BetriceCommon.SUFFIX_CURRENT_PAGE));
        // 步骤1、2、3，获取总页数、当前页、生成带页码的URL
        String pgUrl = housePriceRedisComponent.generatePageUrl(url, totalPg, currentPg);
        // 生成HTTP请求、组装参数并发送请求
        Map<String, String> param = Map.of("_t", "1");
        BetriceHttpClient betriceHttpClient = BetriceHttpBuilder.create()
                .setHttpRequest(RequestMethod.GET, pgUrl, param)
                .build();
        String resultJson = httpClientComponent.doExecute(betriceHttpClient);
        // 截取业务对象
        JSONObject data = JSONObject.parseObject(resultJson).getJSONObject("data");
        Integer queryTotalCount = data.getInteger("total");
        // 步骤4：判断是否需要重置总页数
        totalPg = housePriceRedisComponent.checkSaveRedisTotalPage(totalPg, queryTotalCount, name);
        List<HousePriceVo> housePriceVoList = Optional.ofNullable(data.getJSONArray("list").toJavaList(HousePriceVo.class))
                .orElseThrow(() -> new BetriceException(BetriceExceptionConstant.PARSE_JSON_EXP.getMessage()));
        List<HousePricePo> housePricePoList = UCopy.fullCopyCollections(housePriceVoList, HousePricePo.class);
        // 检查并保存
        this.checkSaveAssemblePo(housePricePoList);
        // 步骤5：最后再修改Redis中的total、current
        housePriceRedisComponent.updateTotalCurrentPg(totalPg, currentPg, name);
    }

    @Override
    public void checkSaveAssemblePo(List<HousePricePo> housePricePoList) {
        Set<String> sysIds = housePricePoList.stream().map(HousePricePo::getSysId).collect(Collectors.toSet());
        LambdaQueryWrapper<HousePricePo> queryWrapper = new QueryWrapper<HousePricePo>().lambda();
        queryWrapper.in(HousePricePo::getSysId, sysIds);
        List<HousePricePo> list = Optional.ofNullable(this.list(queryWrapper)).orElseGet(ArrayList::new);
        List<HousePricePo> result = UCopy.checkAssemble(housePricePoList, list, HousePricePo::getSysId, PASS_DAY_THREHOLD);
        this.saveOrUpdateBatch(result);
    }

    @Override
    public List<HousePricePo> queryByGroupId(String groupId) {
        LambdaQueryWrapper<HousePricePo> queryWrapper = new QueryWrapper<HousePricePo>().lambda();
        queryWrapper.eq(HousePricePo::getGroupId, groupId);
        return this.list(queryWrapper);
    }
}
